Skip to content

feat: python no more#344

Merged
Zygimantass merged 96 commits into
mainfrom
api-rs-control-plane
Jun 11, 2026
Merged

feat: python no more#344
Zygimantass merged 96 commits into
mainfrom
api-rs-control-plane

Conversation

@Zygimantass

Copy link
Copy Markdown
Member

No description provided.

@gakonst gakonst left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM I think

Comment on lines +15 to +24
pub struct SandboxIoParts {
pub stdin: SandboxWrite,
pub stdout: SandboxRead,
pub stderr: SandboxRead,
pub guard: SandboxIoGuard,
}

pub struct SandboxIoGuard {
_inner: Box<dyn Send>,
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

},
};

use async_trait::async_trait;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't async trait no longer necsesary bc it's in std rust?

sandboxes: Mutex<HashMap<SandboxId, Arc<Mutex<LocalSandbox>>>>,
}

struct LocalSandbox {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be separaete local.rs file

Comment on lines +213 to +214
pub fn empty_object() -> Value {
Value::Object(serde_json::Map::new())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inline this

Comment on lines +127 to +202
let execution = self
.store
.create_execution(thread_key, default_metadata(input.metadata))
.await?;
let execution = self
.store
.mark_execution_running(&execution.execution_id)
.await?;
let sandbox_id = self
.ensure_session_sandbox(
thread_key,
session.sandbox_id.as_deref(),
&execution.execution_id,
)
.await?;

self.store
.append_event(
thread_key,
Some(&execution.execution_id),
"session.execution_started",
json!({
"execution_id": execution.execution_id,
"thread_key": thread_key.as_str(),
"input_line_count": input.input_lines.len(),
}),
)
.await?;

let write_result = match self.ensure_session_pipe(thread_key, &sandbox_id).await {
Ok(pipe) => write_input_lines(&pipe, &input.input_lines).await,
Err(error) => Err(error),
};

match write_result {
Ok(()) => {}
Err(error) => {
let error_message = error.to_string();
let _ = self
.store
.append_event(
thread_key,
Some(&execution.execution_id),
"session.execution_failed",
json!({
"execution_id": execution.execution_id,
"thread_key": thread_key.as_str(),
"error": error_message,
}),
)
.await;
let _ = self
.store
.fail_execution(&execution.execution_id, &error_message)
.await;
return Err(error);
}
}

self.store
.append_event(
thread_key,
Some(&execution.execution_id),
"session.execution_completed",
json!({
"execution_id": execution.execution_id,
"thread_key": thread_key.as_str(),
"completion_reason": "input_accepted",
}),
)
.await?;

Ok(self
.store
.complete_execution(&execution.execution_id)
.await?)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should these be atomic commits?


tokio::spawn(async move {
let result =
run_stdout_pump(store.clone(), thread_key.clone(), &pump_key, stdout, guard).await;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wtf who has ever used the word stdout pump???

* refactor(api-rs): use owned sandbox io streams

* refactor(api-rs): move session streaming into runtime

* refactor(api-rs): remove mock session runtime branch

* refactor(api-rs): move sandbox workload modes into runtime

* refactor(api-rs): clean up session API client and e2e tests

* refactor(api-rs): use library sse event types

* refactor(api-rs): address owned io review comments
Zygimantass added a commit that referenced this pull request Jun 12, 2026
Reverts the user feedback feature (#500, #508; both landed on main via the
#344 squash, so this is a manual revert):

- slackbotv2: feedback_buttons blocks on final answers, the 👎 details
  modal, the action/modal-submit handlers, and their tests
- api-rs: POST /api/feedback, the request/response types, the session
  runtime/store create_feedback path, and the ExecutionNotFound mapping

The 0010_user_feedback migration and table are intentionally KEPT: the
migration has already been applied in staging and prod, and removing an
applied migration makes sqlx fail every boot with VersionMissing. The
table is harmless while unused.

The Slack app manifests were already reverted (no shortcut, no commands
scope); interactivity stays enabled but nothing renders interactive
elements anymore.

Amp-Thread-ID: https://ampcode.com/threads/T-019eb82e-5bc9-707f-9d5c-cdb6c9d16926

Co-authored-by: Centaur AI <ai@centaur.local>
Co-authored-by: Amp <amp@ampcode.com>
This was referenced Jun 12, 2026
cjustice added a commit to cjustice/centaur that referenced this pull request Jun 12, 2026
…ools

The Rust codex blocks bridge spawned `codex app-server` before reading any
input, so the per-turn `thread_key` never reached the agent's tool
subprocesses as SLACK_CHANNEL/SLACK_THREAD_TS. `slack-upload` therefore
aborted with "SLACK_CHANNEL not set" and the agent could not deliver files
back into the originating Slack thread.

The Python codex-app-wrapper derived these vars from the thread_key "before
the app server first starts" (export_slack_thread_env); that behavior was
dropped when the Rust harness replaced the wrapper in paradigmxyz#344.

Restore it for the codex blocks path: defer the codex app-server spawn until
the first user turn and, before spawning, parse the thread_key out of the
blocks line and export SLACK_CHANNEL/SLACK_THREAD_TS so the child — and the
tool subprocesses it runs — inherit them. Supports both `slack:<channel>:<ts>`
(api-rs) and legacy `slack:<team>:<channel>:<ts>` shapes; no-op for non-Slack
threads.

The claude-code blocks path (run_blocks_app_server) has the same gap but is a
separate generic codepath; left out of this focused fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cjustice added a commit to cjustice/centaur that referenced this pull request Jun 12, 2026
The sandbox image CMD and the chart's sandbox.harnessEngine both default to
claude-code, carried in from the api-rs migration (paradigmxyz#344). Both carry a NOTE
saying it's a "preview-463 dogfood default — flip back to codex before merging",
but it shipped to main un-reverted.

Because the harness engine is fixed by the image CMD (harness-server
codex|claude-code|amp) with no values/env override, this makes claude-code the
de-facto default for every deployment tracking the chart at main — including
those provisioned for codex (OPENAI_API_KEY), which then fail with
"Not logged in" since no Anthropic credential is wired. codex is also the native
protocol (Codex App Server V2) and harness-server's own no-arg default.

Restore the documented-intended default:
- services/sandbox/Dockerfile: CMD -> ["harness-server", "codex"]
- contrib/chart/values.yaml: sandbox.harnessEngine -> codex

(Operators dogfooding claude-code can still set sandbox.harnessEngine + the CMD.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants